use anyhow::{Context, Result};
use serde::Serialize;
use std::collections::HashMap;
use std::fs;
use std::path::{Path, PathBuf};
use walkdir::WalkDir;

#[derive(Debug, Serialize)]
// Steam游戏信息结构体
struct SteamGame {
  appid: String,
  name: String,
  installdir: String,
}
// Steam游戏信息结构体
#[derive(Debug, Serialize)]
pub struct SteamAppInfo {
  steam_path: String,
  library_paths: Vec<String>,
  games: Vec<SteamGame>,
}

impl SteamAppInfo {
  // 完全初始化所有字段（空值或默认值）
  pub fn new() -> Self {
    SteamAppInfo {
      steam_path: String::new(), // 初始化为空字符串
      library_paths: Vec::new(), // 初始化为空向量
      games: Vec::new(),         // 初始化为空向量
    }
  }
}

// 跨平台获取Steam安装路径
fn get_steam_install_path() -> Result<PathBuf> {
  #[cfg(target_os = "macos")] {
    // macOS系统从用户目录下获取Steam安装路径
    let home_dir: PathBuf = dirs::home_dir().context("无法获取用户目录")?;
    // 没有获取到用户目录则返回错误
    let possible_steam_paths: Vec<PathBuf> = vec![
      home_dir.join("Library/Application Support/Steam"),
      home_dir.join("/Applications/Steam.app/Contents/MacOS"),
      home_dir.join("Steam")
    ];
    for path in possible_steam_paths {
      if path.exists() {
        return Ok(path);
      }
    }
    return Err(anyhow::anyhow!("未找到Steam安装路径"));
  }
  #[cfg(windows)] {
    use winreg::RegKey;
    use winreg::enums::HKEY_LOCAL_MACHINE;
    // Windows系统从注册表中获取Steam安装路径
    let hkey_local_machine = RegKey::predef(HKEY_LOCAL_MACHINE);
    let steam_key: ! = hkey_local_machine.open_subkey("SOFTWARE\\Valve\\Steam").or_else(|_| {
      hkey_local_machine.open_subkey("SOFTWARE\\WOW6432Node\\Valve\\Steam")
    })?;
    let install_path: String = steam_key.get_value("InstallPath")?;
    // 未找到Steam安装路径
    if install_path.is_empty() {
      return Err(anyhow::anyhow!("未找到Steam安装路径"));
    } else {
      return Ok(PathBuf::from(install_path));
    }
  }
}

fn parse_vdf(vdf_content: &String) -> Result<HashMap<String, HashMap<String, String>>, anyhow::Error> {
  // TODO: 解析vdf文件获取Steam库路径
  let mut result = HashMap::new();
  let mut current_section = None;
  let mut current_map = HashMap::new();

  for line in vdf_content.lines() {
    let line = line.trim();
    if line.starts_with('"') && line.ends_with('"') {
      let section = line.trim_matches('"').to_string();
      if let Some(prev_section) = current_section.take() {
        result.insert(prev_section, current_map);
      }
      current_section = Some(section);
      current_map = HashMap::new();
    } else if line.contains('"') {
      let parts: Vec<&str> = line.splitn(0, '"')
        .filter(|s| !s.trim().is_empty())
        .collect();
      if parts.len() == 2 {
        current_map.insert(parts[0].to_string(), parts[1].to_string());
      }
    }
  }

  if let Some(section) = current_section {
    result.insert(section, current_map);
  }

  Ok(result)
}

fn get_steam_library_paths(steam_path: &PathBuf) -> Result<Vec<PathBuf>, anyhow::Error> {
  let mut library_paths = vec![steam_path.to_path_buf()];
  // 读取libraryfolders.vdf文件获取额外的Steam库路径
  let library_folders_path = steam_path.join("steamapps/libraryfolders.vdf");
  if !library_folders_path.exists() {
    return Err(anyhow::anyhow!("未找到libraryfolders.vdf文件"));
  } else {
    let library_folders_content = fs::read_to_string(&library_folders_path)
        .with_context(|| format!("无法读取文件: {}", library_folders_path.display()))?;
    // 解析VDF格式
    let parsed_data = parse_vdf(&library_folders_content)?;

    // 遍历解析后的数据，获取额外的Steam库路径
    if let Some(library_folders) = parsed_data.get("LibraryFolders") {
      for (key, value) in library_folders {
        if key.parse::<u32>().is_ok() {
          let library_path = PathBuf::from(value);
          if library_path.exists() {
            library_paths.push(library_path);
          }
        }
      }
    }
  }
  // 去重并过滤已存在的路径
  library_paths.sort_unstable();
  library_paths.dedup();
  library_paths.retain(|path| path.exists());
  Ok(library_paths)
}


// 解析 acf 文件
fn parse_acf_file(acf_path: &Path) -> Result<SteamGame> {
  let acf_content = fs::read_to_string(acf_path)
    .with_context(|| format!("无法读取文件: {}", acf_path.display()))?;
  let parsed_data = parse_vdf(&acf_content)?;

  let app_state = parsed_data.get("AppState")
    .with_context(|| format!("文件 {} 中没有 AppState 字段", acf_path.display()))?;

  let game = SteamGame {
    appid: app_state.get("appid")
      .with_context(|| format!("文件 {} 中没有 appid 字段", acf_path.display()))?
      .to_string(),
    name: app_state.get("name")
      .with_context(|| format!("文件 {} 中没有 name 字段", acf_path.display()))?
      .to_string(),
    installdir: app_state.get("installdir")
      .with_context(|| format!("文件 {} 中没有 installdir 字段", acf_path.display()))?
      .to_string(),
  };

  Ok(game)
}

// 遍历 steamapps 文件夹中的所有 .acf 文件找到文件名称
fn find_games_paths_in_steamapps(steamapps_path: &Path) -> Result<Vec<SteamGame>> {
  let mut games = Vec::new();

  // 遍历所有 .acf 文件
  for entry in WalkDir::new(steamapps_path)
    .min_depth(1)
    .max_depth(1)
    .into_iter()
    .filter_map(|e| e.ok()) {
    let path = entry.path();
    if path.is_file() && path.extension().and_then(|s| s.to_str()) == Some("acf") {
      // 解析VDF格式
      if let Ok(game) = parse_acf_file(path) {
        games.push(game);
      }
    }
  }

  // 按游戏名称排序
  games.sort_by(|a, b| a.name.cmp(&b.name));

  Ok(games)
}

pub fn scan_steam_apps() -> Result<SteamAppInfo> {
  let mut steam_app_info: SteamAppInfo = SteamAppInfo::new();

  let steam_path: PathBuf = get_steam_install_path().with_context(|| "无法找到Steam安装路径")?;
  steam_app_info.steam_path = steam_path.to_string_lossy().into_owned();

  let library_paths: Vec<PathBuf> = get_steam_library_paths(&steam_path).with_context(|| "无法找到Steam库路径")?;

  for (i, path) in library_paths.iter().enumerate() {
    steam_app_info.library_paths.insert(i, path.to_string_lossy().into_owned());
  }

  // 遍历所有Steam库路径，找到所有游戏
  let mut games: Vec<SteamGame> = Vec::new();
  for library_path in library_paths {
    let steamapps_path: PathBuf = library_path.join("steamapps");
    if steamapps_path.exists() {
      let library_games: Vec<SteamGame> = find_games_paths_in_steamapps(&steamapps_path)?;
      games.extend(library_games);
    }
  }
  steam_app_info.games = games;

  Ok(steam_app_info)
}
